/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2014        */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be        */
/* attached to the FatFs via a glue function rather than modifying it.   */
/* This is an example of glue functions to attach various exsisting      */
/* storage control modules to the FatFs module with a defined API.       */
/*-----------------------------------------------------------------------*/

#include "diskio.h"		/* FatFs lower layer API */
//#include "usbdisk.h"	/* Example: Header file of existing USB MSD control module */
//#include "atadrive.h"	/* Example: Header file of existing ATA harddisk control module */
//#include "sdcard.h"		/* Example: Header file of existing MMC/SDC contorl module */
#include "sd_spi.h"
#include "function_drv.h"
#include "debug.h"
#include "delay.h"

#define SD_CARD	 	0  			//SDcard,volume label is 0
/* Definitions of physical drive number for each drive */
//#define ATA		0	/* Example: Map ATA harddisk to physical drive 0 */
//#define MMC		1	/* Example: Map MMC/SD card to physical drive 1 */
//#define USB		2	/* Example: Map USB MSD to physical drive 2 */


/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	#if 0
	return RES_OK;
	#else
  switch (pdrv)
	{
		case 0 :
			return RES_OK;
		case 1 :
			return RES_OK;
		case 2 :
			return RES_OK;
		default:
			return STA_NOINIT;
	}
	#endif
}



/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	#if 0
	uint8_t res=0;	    	
  if(pdrv==0)
  {
		res = SD_Init();
	}	
	if(res)return  STA_NOINIT;
	else return 0; 				//Initialization succeeded
	#else
  uint8_t res;
	res = SD_init(); 
	//STM32 SPI bug. If the following statement is not executed when the sd card operation fails, SPI read and write exceptions may be caused
			if(res)
			{
				SD_SPIx_SetSpeed(Speed_Low); 
				SD_SPIx_ReadWriteByte(0xff);//Provide additional 8 clocks
				SD_SPIx_SetSpeed(Speed_High); 
//				printf("sd init error:  \r\n");
			}
	if(res)return  STA_NOINIT;
	else return RES_OK; 		//Initialization succeeded
	#endif
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address in LBA */
	UINT count		/* Number of sectors to read */
)
{
	#if 0
	uint8_t res=0; 
    if (!count)return RES_PARERR;//Count cannot be equal to 0, otherwise parameter error will be returned
	if(pdrv==0)
	{
		  res=SD_ReadMultiBlock(buff,sector,count);
			while(res)//Read error
			{
				SD_Init();	//Reinitialize SD card
				res=SD_ReadMultiBlock(buff,sector,count);
//				printf("sd re error:%d\r\n",res);
			}
	}
	else
		res = 1;
   //Process the return value and set The return value of sd_spi.c is converted to the return value of ff. c
    if(res==0x00)return RES_OK;	 
    else return RES_ERROR;
	#else
  uint8_t res;
	if( !count )
	{    
		return RES_PARERR;  /* Count cannot be equal to 0, otherwise parameter error will be returned */
	}
	switch (pdrv)
	{
		case 0:
		    res=SD_ReadDisk(buff,sector,count);	 
				if(res == 0){
					return RES_OK;
				}else{
//					printf("sd re error:%d\r\n",res);
					return RES_ERROR;
				}                                               
		default:
			return RES_ERROR;
	}
	#endif
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if _USE_WRITE
DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address in LBA */
	UINT count			/* Number of sectors to write */
)
{
	#if 0
	uint8_t res=0;  
    if (!count)return RES_PARERR;//Count cannot be equal to 0, otherwise parameter error will be returned	 
	if(pdrv==0)
	{
			res=SD_WriteMultiBlock((uint8_t*)buff,sector,count);
			while(res)//Write error
			{
				SD_Init();	//Reinitialize SD card
				res=SD_WriteMultiBlock((uint8_t*)buff,sector,count);	
//				printf("sd wr error:%d\r\n",res);
			}
	}
	else 
		res = 1;
    //Process the return value and set The return value of sd_spi.c is converted to the return value of ff. c
    if(res == 0x00)return RES_OK;	 
    else return RES_ERROR;
	#else
	  uint8_t  res;
	if( !count )
	{    
		return RES_PARERR;  /* Count cannot be equal to 0, otherwise parameter error will be returned */
	}
	switch (pdrv)
	{
		case 0:
		    res=SD_WriteDisk((uint8_t *)buff,sector,count);
				if(res == 0){
					return RES_OK;
				}else{
//						printf("sd wr error:%d\r\n",res);
					return RES_ERROR;
				}                                                
		default:return RES_ERROR;
	}
	#endif
}
#endif


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

#if _USE_IOCTL
DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	#if 0
DRESULT res;						  			     
	if(pdrv==SD_CARD)//SDcard
	{
	    switch(cmd)
	    {
		    case CTRL_SYNC:
				res = RES_OK; 
		        break;	 
		    case GET_SECTOR_SIZE:
				*(DWORD*)buff = 512; 
		        res = RES_OK;
		        break;	 
		    case GET_BLOCK_SIZE:
				*(WORD*)buff = 512*8;//SDCardInfo.CardBlockSize;
		        res = RES_OK;
		        break;	 
		    case GET_SECTOR_COUNT:
		        *(DWORD*)buff = (uint32_t)SD_GetCapacity*1024*1024/512;
		        res = RES_OK;
		        break;
		    default:
		        res = RES_PARERR;
		        break;
	    }
	}else res=RES_ERROR;//Others are not supported
    return res;
	#else
    DRESULT res;
	 switch(cmd)
	    {
		    case CTRL_SYNC:
						SD_CS(1);
						do{
//							HAL_Delay(20);
							DelayMS(1);
//							printf("DelayMS 20  \r\n" );

						}while(SD_SPIx_ReadWriteByte(0xFF)!=0xFF);
						res=RES_OK;
						SD_CS(0);
		        break;	 
		    case GET_SECTOR_SIZE:
		        *(WORD*)buff = 512;
		        res = RES_OK;
		        break;	 
		    case GET_BLOCK_SIZE:
		        *(WORD*)buff = 8;
		        res = RES_OK;
		        break;	 
		    case GET_SECTOR_COUNT:
		        *(DWORD*)buff = SD_GetSectorCount();
		        res = RES_OK;
		        break;
		    default:
		        res = RES_PARERR;
		        break;
	    }
		return res;	
	#endif
}


DWORD get_fattime(void)
{
    
    return 0;
}
#endif
